package com.androidvizlab.bachelor.Sockets;

import android.util.Log;

import com.androidvizlab.bachelor.notifications.NoticeManager;
import com.ibm.mqtt.IMqttClient;
import com.ibm.mqtt.MqttClient;
import com.ibm.mqtt.MqttException;
import com.ibm.mqtt.MqttPersistence;
import com.ibm.mqtt.MqttSimpleCallback;

/**
 * This the client for the MQTT Broker that receives update on available data from the calibration
 * 
 * @author TheHive
 *
 */
public class DataPushMqttClient implements Runnable{

	//Connection variables
	private String brokerConString = "tcp://"; //connection string
	private String brokerHostName = "192.168.1.90"; //brokername (IP)
	private int brokerPortNumber = 1883; //default port number
	private boolean cleanStart = false; //determines if the client would like to have a clean start
	
	//Mqtt Client and persistence
	private String clientID = "VzLQESAR2421"; //mqtt client id
	private IMqttClient mqttClient = null; //mqtt client to connect to the broker 
	private MqttPersistence persistence = null;
	
	//Message and data
	private String[] topics = null; //list of topics to subscribe to
	private int[] qualityOfService = {0}; //the quality of service of the messages
	
	//Ping and keep alive
	private short keepalive = 20 * 60; //in seconds
	
	//SimpleCallBack handler
	private MqttSimpleCallback callbackhandler = null;
	
	//
	private boolean isConnectedToBroker = false;
	
	//STATUS BAR NOTIFICATION
	private NoticeManager noticemanager = null;
	
	public DataPushMqttClient(String clientID, MqttSimpleCallback callbackhandler, NoticeManager noticemanager)
	{
		//this.clientID = clientID;
		this.callbackhandler = callbackhandler;
		this.noticemanager = noticemanager;
	}

	@Override
	public void run() {
		
		setUpMqttClientAndCallback();
	
		if(isConnectedToBroker == false)
		{
			//Notify user that the service is up and running
			noticemanager.createNotification("Service running", "Service is up and running", NoticeManager.NOTIFICATION_AUTOCANCEL);
			
			if(connectToMqttBroker())
			{
				noticemanager.createNotification("Service connected", "conected", NoticeManager.NOTIFICATION_AUTOCANCEL);
				subscribe("new_available_data");
			}
			else
			{
				noticemanager.createNotification("Could not connect", "not conected", NoticeManager.NOTIFICATION_AUTOCANCEL);
			}
		}
	}
	
	
	public void stop()
	{
		
	}
	
	//******* BROKER CONNECTION and CLIENT SETUP *********//
	
	/**
	 * Create and setup MqttClient
	 */
	public void setUpMqttClientAndCallback()
	{
		brokerConString += brokerHostName +"@"+ brokerPortNumber;
		try
		{
			mqttClient = MqttClient.createMqttClient(brokerConString, persistence);
			mqttClient.registerSimpleHandler(callbackhandler);
		}
		catch(MqttException e)
		{
			mqttClient = null;
			//todo
		}
	}
	
	//CONNECT TO MQTT BROKER
	/**
	 * Connects to MQTT broker
	 * @return
	 */
	public boolean connectToMqttBroker()
	{
		try
		{
			mqttClient.connect(clientID, cleanStart, keepalive);
			isConnectedToBroker = true;
			Log.i("datapushconnected","subscriber client is now connected to broker");
			noticemanager.createNotification("Broker connection", "Client is now connected", NoticeManager.NOTIFICATION_AUTOCANCEL);
		}
		catch(MqttException e)
		{
			isConnectedToBroker = false;
			//todo
		}
		return isConnectedToBroker;
	}
	
	//DISCONNECT FROM MQTT BROKER
	/**
	 * Disconects from the MQTT broker
	 */
	public void disconnectFromMqttBroker()
	{
		try
		{
			if(mqttClient != null)
			{
				mqttClient.disconnect();
				isConnectedToBroker = false;
			} 
		}
		catch(MqttException e)
		{
			//todo
		}
	}
	
	//SUBSCRIBE TO TOPIC
	/**Method: client subscribe to topic/topics to be notify if there are publish info.
	*regarding the given topic(s)
	*/
	public void subscribe(String topic)
	{
		topics = new String[]{topic};
		
		if(isConnectedToBroker == true)
		{
			try
			{
				mqttClient.subscribe(topics, qualityOfService); //subscribe to a given topic(s) specifying the quality of service
				Log.i("datapushsubscription","subscriber client is now subscribed to topics");
				//notify the user that the service has successfully subscribe
			}
			catch(MqttException e)
			{
				//notify user of error
			}
		}
	}
	
	//PING BROKER
	public void sendPINGMsgToBroker() throws MqttException
	{
		mqttClient.ping();
	}

	//****** GETTERS AND SETTERS *******//
	
	public String getBrokerConString() {
		return brokerConString;
	}

	public void setBrokerConString(String brokerConString) {
		this.brokerConString = brokerConString;
	}

	public String getBrokerHostName() {
		return brokerHostName;
	}

	public void setBrokerHostName(String brokerHostName) {
		this.brokerHostName = brokerHostName;
	}

	public int getBrokerPortNumber() {
		return brokerPortNumber;
	}

	public void setBrokerPortNumber(int brokerPortNumber) {
		this.brokerPortNumber = brokerPortNumber;
	}

	public boolean isCleanStart() {
		return cleanStart;
	}

	public void setCleanStart(boolean cleanStart) {
		this.cleanStart = cleanStart;
	}

	public MqttPersistence getPersistence() {
		return persistence;
	}

	public void setPersistence(MqttPersistence persistence) {
		this.persistence = persistence;
	}

	public String[] getTopics() {
		return topics;
	}

	public void setTopics(String[] topics) {
		this.topics = topics;
	}

	public int[] getQualityOfService() {
		return qualityOfService;
	}

	public void setQualityOfService(int[] qualityOfService) {
		this.qualityOfService = qualityOfService;
	}

	public short getKeepalive() {
		return keepalive;
	}

	public void setKeepalive(short keepalive) {
		this.keepalive = keepalive;
	}	
}
